/**
 * 一些通用方法的Module
 * @namespace Utils
 */
var Utils = (function ($) {

    /**
     * 项目路径
     */
    var CONTEXT_PATH = $(location).attr('pathname').substring(0, $(location).attr('pathname').substring(1).indexOf('/') + 1);
    
    /**
     * 初始化的一些参数
     */
    var INIT_CONSTANT = {
        width: $(window).width() * 0.85,
        height: $(window).height() - 5,
        pageLimits: [10,15,30,50,100,1000]
    };

    var ALL_SHOP_PRODUCT_TYPE = [
        {key: "1", value: "快餐"},
        {key: "2", value: "药品"},
        {key: "3", value: "百货"},
        {key: "4", value: "脏衣服收"},
        {key: "5", value: "干净衣服派"},
        {key: "6", value: "生鲜"},
        {key: "8", value: "高端饮品"},
        {key: "9", value: "现场勘验"},
        {key: "10", value: "快递"},
        {key: "12", value: "文件"},
        {key: "13", value: "蛋糕"},
        {key: "14", value: "鲜花"},
        {key: "15", value: "数码"},
        {key: "16", value: "服装"},
        {key: "17", value: "汽配"},
        {key: "18", value: "珠宝"},
        {key: "20", value: "披萨"},
        {key: "22", value: "水产"},
        {key: "27", value: "专人直送"},
        {key: "32", value: "中端饮品"},
        {key: "33", value: "便利店"},
        {key: "34", value: "面包糕点"},
        {key: "35", value: "火锅"},
        {key: "36", value: "证照"},
        {key: "40", value: "烧烤小龙虾"},
        {key: "41", value: "外部落地配"},
        {key: "47", value: "烟酒行"},
        {key: "48", value: "成人用品"},
        {key: "99", value: "其他"}
    ];

    var ALL_SHOP_STATUS = [
        {key: "0", value: "待审核"},
        {key: "1", value: "已通过"},
        {key: "2", value: "未通过"}
    ];

    var ALL_API_CODE = [
        {key: "00", value: "查询店铺"},
        {key: "01", value: "新增店铺"},
        {key: "02", value: "修改店铺"},
        {key: "03", value: "通知建店结果"}
    ];

    var ALL_API_TYPE = [
        {key: "01", value: "作为服务端"},
        {key: "02", value: "作为客户端"}
    ];

    var ALL_HOT_CITY = [
        {key: "000000", value: "全国"},
        {key: "010000", value: "北京"},
        {key: "020000", value: "上海"},
        {key: "030200", value: "广州"},
        {key: "040000", value: "深圳"},
        {key: "180200", value: "武汉"},
        {key: "200200", value: "西安"},
        {key: "080200", value: "杭州"},
        {key: "070200", value: "南京"},
        {key: "090200", value: "成都"},
        {key: "060000", value: "重庆"},
        {key: "030800", value: "东莞"},
        {key: "230300", value: "大连"},
        {key: "230200", value: "沈阳"},
        {key: "070300", value: "苏州"},
        {key: "250200", value: "昆明"},
        {key: "190200", value: "长沙"},
        {key: "150200", value: "合肥"},
        {key: "080300", value: "宁波"},
        {key: "170200", value: "郑州"},
        {key: "050000", value: "天津"},
        {key: "120300", value: "青岛"},
        {key: "120200", value: "济南"},
        {key: "220200", value: "哈尔滨"},
        {key: "240200", value: "长春"},
        {key: "110200", value: "福州"}
    ];

    var ALL_COMPANY_TYPE = [
        {key: "01", value: "事业单位"},
        {key: "02", value: "创业公司"},
        {key: "03", value: "合资"},
        {key: "04", value: "国企"},
        {key: "05", value: "外企代表处"},
        {key: "06", value: "外资（欧美）"},
        {key: "07", value: "外资（非欧美）"},
        {key: "08", value: "已上市"},
        {key: "09", value: "政府机关"},
        {key: "10", value: "民营"},
        {key: "11", value: "非营利组织"},

    ];

    /**
     * 其它允许的键盘key
     * @param {Number} key
     * @returns {boolean}
     */
    var isOtherAllowKey = function (key) {
        // Backspace(退格) || 回车 || 左 || 右 || delete || 大小写切换键 || shift
        return key === 8 || key == 13 || key == 37 || key == 39 || key == 46 || key == 20 || key == 16;
    };

    /**
     * 如果是键盘小数
     * @param {Number} key
     * @returns {boolean}
     */
    var isNumberKeyCode = function (key) {
        return (key >= 96 && key <= 105) || (key >= 48 && key <= 57); // 键盘右边数字区 || 键盘字母区域上方数字
    };

    /**
     * 如果是键盘输入字母，除去3个字母：I O Q
     * @param {Number} key
     * @returns {boolean}
     */
    var isEnglishLetter = function (key) {
        return key >= 65 && key <= 90;
    };

    /**
     * 字母：I O Q
     * @param key
     * @returns {boolean}
     */
    var isIOQLetter = function (key) {
        return key === 73 || key === 79 || key === 81;
    };

    return {

        isNumberKeyCode: isNumberKeyCode,
        isEnglishLetter: isEnglishLetter,
        isIOQLetter: isIOQLetter,
        isOtherAllowKey: isOtherAllowKey,

        hasChinese: function (str) {
            return /[^x00-xff]|[\@]/g.test(str);
        },

        clearChinese: function (str) {
            return (str || "").replace(/[^x00-xff]|[\@]/g, "");
        },

        clearIOQ: function (str) {
            return (str || "").replace(/[ioqIOQ]/g, "");
        },

        /**
         * 只取英文字母与数据
         * @param str
         * @returns {*|XML|string|void}
         */
        fetchEngDig: function (str) {
            return (str || "").replace(/[^a-zA-Z0-9]/g, "");
        },

        /*根据品牌型号解析出公告号，第一段字母和数字*/
        getLogicBrandModel: function (inputBrandModel) {
            if (inputBrandModel) {
                var regExp = new RegExp("[a-zA-Z0-9]+");
                var brandModels = inputBrandModel.match(regExp);//返回数组对象
                if (brandModels && brandModels.length > 0) {
                    return brandModels[0];
                } else {
                    return "";
                }
            } else {
                return "";
            }
        },
        /**
         * 手动刷新时，记录当前选中页面
         * @param {String} controlId
         * @memberOf Utils
         */
        setLocationHash: function (controlId) {
            window.location.hash = controlId;
            document.cookie = "hash=" + controlId.replace(",", "+");

            // bug #13961
            setTimeout(function () {
                $(window).scrollTop();
            }, 0);
        },

        /**
         * 手动刷新时，记录当前选中页面
         * @returns {string}
         * @memberOf Utils
         */
        getLocationHash: function () {
            return ObjectUtils.htmlEncode(window.location.hash);
        },
        /**
         * 取消画面上的文字选择, 一般用于在双击时把选择的文字取消掉
         * @memberOf Utils
         */
        unselectedText: function () {
            if (window.getSelection) {
                window.getSelection().removeAllRanges();
            } else if (document.selection) {
                document.selection.empty();
            }
        },

        /**
         * A 乘以 B 返回结果 fractionalDigits:保留几位小数
         * @param a {String|Number} 一个数字
         * @param b {String|Number} 另外一个数字
         * @param fractionalDigits {Number} 几位小数
         * @returns {Number} 结果
         * @memberOf Utils
         */
        multiply: function (a, b, fractionalDigits) {
            if (!a) {
                a = new Decimal(0);
            } else {
                a = new Decimal(a + "");
            }

            if (!b) {
                b = new Decimal(0);
            } else {
                b = new Decimal(b + "");
            }
            return a.times(b).toFixed(fractionalDigits);
        },

        /**
         * 功能: 函数节流避免程序频繁被调用，只有被调用的时间间隔大于延迟时间时函数才会被执行。
         * 参数: 传递一个执行函数和时间间隔
         * @param {Function} fn
         * @param {Number} delay
         * @returns {Function}
         * @memberOf Utils
         */
        throttle: function (fn, delay) {
            var timer = null;
            return function () {
                var context = this, args = arguments;
                clearTimeout(timer);
                timer = setTimeout(function () {
                    fn.apply(context, args);
                }, delay);
            };
        },

        /**
         * 心跳函数：
         * 这个函数返回一个函数，当这个函数被频繁调用时，就会心跳，否则停止心跳。
         * @param func {function()} 心跳函数
         * @param interval {Number} 心跳时间
         * @returns {function()}
         * @memberOf Utils
         */
        heartbeat: function (func, interval) {
            var lastAliveTime = (new Date()).getTime();
            setInterval(function () {
                if ((new Date()).getTime() - lastAliveTime < interval) {
                    func();
                }
            }, interval);
            return function () {
                lastAliveTime = (new Date()).getTime();
            };
        },
        /**
         * 页面刷新/离开提示
         * @param {Function=} validateChangeFun
         * @memberOf Utils
         */
        addLeavePageConfirm: function (validateChangeFun) {
            var title = document.title;
            $(window).bind("beforeunload", function () {
                document.title = title;
                if (validateChangeFun && typeof(validateChangeFun) == "function" && !validateChangeFun()) {//无修改
                    return undefined;
                }
                return "";
            });
        },

        /**
         * 页面刷新/离开提示
         * @memberOf Utils
         */
        removeLeavePageConfirm: function () {
            $(window).unbind("beforeunload");
        },

        /**
         * 同步ajax调用
         * @param {{}} param
         * @param {String} url
         * @param {String=} type
         * @param {Boolean=} async
         * @returns {ConfigUnit}
         * @memberOf Utils
         */
        loadAjaxData: function (param, url, type, async) {
            var returnData = null;
            $.ajax({
                url: url,
                data: param,
                type: type || "POST",
                async: async || false,
                success: function (data) {
                    returnData = data;
                }
            });
            return returnData;
        },

        /**
         * url加时间戳
         * @param {String} url
         * @memberOf Utils
         * @returns {string}
         */
        addTimeStamp4URL: function (url) {
            var timstamp = (new Date()).valueOf();
            url = url + "?timstamp=" + timstamp;
            return url;
        },

        /**
         * 功能：金额按千位逗号分割，返回格式化后的数值字符串.
         * @param {Number|String} s, 需要格式化的金额数值.
         * @param {Number|String} type, 判断格式化后的金额是否需要小数位.
         * @returns {String}
         * @memberOf Utils
         */
        formatMoney: function (s, type) {
            if (!s && "0" != s) return "";
            if (/^[+\-][^0-9\.]/.test(s)) return "0.00";
            if (s == null || s == "") return "0.00";
            s = s.toString().replace(/^(\d*)$/, "$1.");
            s = (s + "00").replace(/(\d*\.\d\d)\d*/, "$1");
            s = s.replace(".", ",");
            var re = /(\d)(\d{3},)/;
            while (re.test(s))
                s = s.replace(re, "$1,$2");
            s = s.replace(/,(\d\d)$/, ".$1");
            if (type == 0) {// 不带小数位(默认是有小数位)
                var a = s.split(".");
                if (a[1] == "00") {
                    s = a[0];
                }
            }
            return s;
        },

        /**
         * 将数值四舍五入后格式化(千分位), 返回格式的字符串,如'1,234,567.00'
         * @memberOf Utils
         * @param {Number|String} num
         * @param {Number} maxCent 要保留的最大小数位数
         * @param {Number} minCent 要保留的最小小数位数
         * @param {Number=} isThousand 是否需要千分位 0:不需要,1:需要(数值类型)
         * @returns {string}
         */
        formatNumberForThousand: function (num, maxCent, minCent, isThousand) {
            num = (num + "").replace(/[ ]/g, "");
            if (num === 'null' || num === "" || isNaN(num)) {
                return "";
            }
            var signVal = num; // 用来判断正负号
            num = Math.abs(num);// 去掉合法数字前的0，如‘0098’转为‘98’
            num = num.toString().replace(/\$|\,/g, '');
            //确保传入小数位为数值型数值.
            if (isNaN(maxCent)) {
                maxCent = 0;
            }
            if (isNaN(minCent)) {
                minCent = 0;
            }
            //求出小数位数,确保为正整数.
            maxCent = parseInt(maxCent);
            maxCent = Math.abs(maxCent);
            minCent = parseInt(minCent);
            minCent = Math.abs(minCent);

            //确保传入是否需要千分位为数值类型.
            if (isNaN(isThousand)) {
                isThousand = 0;
            }
            isThousand = parseInt(isThousand);
            if (isThousand < 0) {
                isThousand = 0;
            }
            if (isThousand >= 1) {//确保传入的数值只为0或1
                isThousand = 1;
            }

            var cent = 0;// 前台显示的数据的小数的位数(minCent~maxCent)
            var decimalPart = '0'; // 整数部分数据
            var integerPart = '0'; // 小数部分数据
            var valueStr = num.toString();
            var index = valueStr.indexOf(".");
            if (index == -1) {
                cent = minCent;
                integerPart = valueStr;
            } else {
                decimalPart = valueStr.substring(index + 1, valueStr.length);
                var decimalLen = decimalPart.length;
                if (decimalLen <= minCent) {
                    cent = minCent;
                } else if (decimalLen >= maxCent) {
                    cent = maxCent;
                } else {
                    cent = decimalLen;
                }
                //Math.floor:返回小于等于其数值参数的最大整数
                integerPart = Math.floor(num * Math.pow(10, cent) + 0.50000000001);//把指定的小数位先转换成整数.多余的小数位四舍五入.
                decimalPart = integerPart % Math.pow(10, cent); //求出小数位数值.
                integerPart = Math.floor(integerPart / Math.pow(10, cent)).toString();//求出整数位数值.
                decimalPart = decimalPart.toString();//把小数位转换成字符串,以便求小数位长度.
            }

            while (decimalPart.length < cent) {//补足小数位到指定的位数.
                decimalPart = "0" + decimalPart;
            }

            var sign = signVal == Math.abs(signVal);//获取符号(正/负数)
            if (isThousand == 0) { //不需要千分位符.
                return (((sign) ? '' : '-') + integerPart + '.' + decimalPart);
            } else {//对整数部分进行千分位格式化.
                var reg = /(-?\d+)(\d{3})/;
                while (reg.test(integerPart)) {
                    integerPart = integerPart.replace(reg, "$1,$2");
                }
                return (((sign) ? '' : '-') + integerPart + '.' + decimalPart);
            }
        },

        /**
         * 如果指定项目不存在与数组则添加进去,如果存在,则替换成最新的值
         * @param {Array} array
         * @param {Object} item 项目
         * @param {Function=} comparator 比较器
         * @memberOf Utils
         */
        pushIfNotExist: function (array, item, comparator) {
            var exists = false;
            for (var i = 0, len = array.length; i < len; i++) {
                var obj = array[i];
                if (comparator && comparator.apply({}, [obj, item]) || obj === item) {
                    exists = true;
                    // 存在,替换成最新的值
                    array[i] = item;
                    break;
                }
            }
            // 不存在,则添加
            if (!exists) {
                array.push(item);
            }

            return !exists;
        },

        /**
         * 移除制定项目或者方法的数据
         * @param {Array} array 数组
         * @param item {Array|Object|Function},项目
         * @return {Array} 已经删除的数组对象
         * @memberOf Utils
         */
        remove: function (array, item) {
            // 存放删除的对象
            var removeList = [];
            if (array == null || array.length <= 0) {
                return removeList;
            }

            var len = array.length;
            while (len--) {
                var obj = array[len];
                if (typeof item === "function" && item.apply(obj, [obj])
                    || item === obj
                    || (_.isArray(item) && item.indexOf(obj) >= 0)) {
                    array.splice(len, 1);
                    // push删除的对象.
                    removeList.push(obj);
                }
            }
            return removeList;
        },

        /**
         * 判断value值是否超过n个字节
         * @param {String} value 传入值
         * @param {Number} n 字节数
         * @return {Boolean} value值是否超过n个字节
         * @memberOf Utils
         */
        characterWidthCheck: function (value, n) {
            var length = 0;
            for (var i = 0; i < value.length; i++) {
                var c = value.charCodeAt(i);
                // 单字节加1, 双字节加2
                if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
                    length++;
                } else {
                    length += 2;
                }
            }
            return length > n;

        },
        /**
         * 获取str的前n个字节的值
         * @param {String} str 传入值
         * @param {Number} n 字节数
         * @return {String}
         * @memberOf Utils
         */
        getDifiniteValue: function (str, n) {
            return str.replace(/([\u0391-\uffe5])/ig, '$1a').substring(0, n).replace(/([\u0391-\uffe5])a/ig, '$1');
        },

        /**
         * add by Losyn 2013-09-18
         * 半角转换为全角函数，全角空格为12288，半角空格为32 其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
         * @memberOf Utils
         * @param {String} txtString
         * @returns {string}
         */
        toDBC: function (txtString) {
            var tmp = "";
            for (var i = 0; i < txtString.length; i++) {
                if (txtString.charCodeAt(i) == 32) {
                    tmp = tmp + String.fromCharCode(12288);
                }
                if (txtString.charCodeAt(i) < 127) {
                    tmp = tmp + String.fromCharCode(txtString.charCodeAt(i) + 65248);
                }
            }
            return tmp;
        },

        /**
         * 全角转换为半角函数
         * @memberOf Utils
         * @param {String} str
         * @returns {string}
         */
        toCDB: function (str) {
            var tmp = "";
            for (var i = 0; i < str.length; i++) {
                if (str.charCodeAt(i) > 65248 && str.charCodeAt(i) < 65375) {
                    tmp += String.fromCharCode(str.charCodeAt(i) - 65248);
                } else {
                    tmp += String.fromCharCode(str.charCodeAt(i));
                }
            }
            return tmp;
        },

        /**
         * 兼容性文本选择范围的方法
         * @param {HTMLElement} html 元素
         * @param {Number} position 文本选择结束的位置
         * @memberOf Utils
         */
        caret: function (element, position) {
            var range, isPosition = position !== undefined;
            if (element.selectionStart !== undefined) {
                if (isPosition) {
                    element.focus();
                    element.setSelectionRange(0, position);
                }
            } else if (document.selection) {
                if ($(element).is(":visible")) {
                    element.focus();
                }
                range = document.selection.createRange();
                if (isPosition) {
                    range.move("character", position);
                    range.select();
                }
            }
        },
        /**
         * val为null时返回默认值
         * @param {Object} val
         * @param {Object} defaultVal 默认值
         * @memberOf Utils
         */
        defaultValue: function (val, defaultVal) {
            return val == null ? defaultVal : val;
        },
        /**
         * 获取对象中属性的值, 例：getFieldValueByPath(CLAIMMODEL, "referenceInfo.accidentInfo.reporter")
         * @param {Object} obj
         * @param {String} fieldPath 属性路径，如"referenceInfo.accidentInfo.reporter"
         * @memberOf Utils
         */
        getFieldValueByPath: function (obj, fieldPath) {
            var subFieldPaths = fieldPath.split(".");
            var fieldValue = obj;
            for (var i = 0; i < subFieldPaths.length; i++) {
                fieldValue = fieldValue[subFieldPaths[i]];
                if (fieldValue == null) {
                    return null;
                }
            }
            return fieldValue;
        },

        /**
         * 获取对象中属性的值, 例：getFieldValueByPath(CLAIMMODEL, "referenceInfo.accidentInfo.reporter")
         * @param {Object} obj
         * @param {String} fieldPath 属性路径，如"referenceInfo.accidentInfo.reporter"
         * @memberOf Utils
         */
        setFieldValueByPath: function (obj, fieldPath, value) {
            var subFieldPaths = fieldPath.split(".");
            var fieldValue = obj;

            for (var i = 0; i < subFieldPaths.length -1; i++) {
                fieldValue = fieldValue[subFieldPaths[i]];

                if (fieldValue == null) {
                    return;
                }
            }

            fieldValue[subFieldPaths[subFieldPaths.length -1]] = value;
        },

        /**
         * 深度clone
         * @param {Object} obj 要克隆的对象
         * @memberOf Utils
         */
        deepClone: function (obj) {
            return (obj instanceof Array) ? $.extend(true, [], obj) : $.extend(true, {}, obj);
        },

        /**
         * 取得文件名的前面部分
         * @param {String} filename
         * @memberOf Utils
         */
        getMainFileName: function (filename) {
            var pos = filename.lastIndexOf(".");
            if (pos < 0 || pos == filename.length) {
                return filename;
            } else {
                return filename.substring(0, pos);
            }
        },

        /**
         * 取得文件名的后面部分
         * @param {String} filename
         * @memberOf Utils
         */
        getExtFileName: function (filename) {
            var pos = filename.lastIndexOf(".");
            if (pos < 0 || pos == filename.length) {
                return "";
            } else {
                return filename.substring(pos + 1);
            }
        },

        /**
         * @memberOf Utils
         * @param {HTMLElement|String|jQuery} $selectors
         * @return {string}
         */
        getGroupValueByUI: function ($selectors) {
            var groupValue = [];
            $($selectors).each(function () {
                $(this).prop("checked") ? groupValue.push($(this).val()) : null;
            });
            return groupValue;
        },

        /**
         *  对定损单状态进行加工，去掉‘转送’字样
         * @param {String} obj
         * @returns {String}
         */
        getStatus: function (obj) {
            if (obj == '') {
                return '';
            } else if (typeof obj == 'string') {
                if (obj.indexOf('(') < 0) {
                    return obj;
                } else {
                    return obj.substr(0, obj.indexOf('('));
                }
            } else {
                return '';
            }
        },

        /**
         *  对定损单状态进行加工，去掉‘转送’字样
         * @param {String} obj
         * @returns {String}
         */
        getSuffix: function (obj) {
            if (obj == '') {
                return '';
            } else if (typeof obj == 'string') {
                if (obj.indexOf('(') < 0) {
                    return '';
                } else {
                    return obj.substr(obj.indexOf('('), obj.length);
                }
            } else {
                return '';
            }
        },
        /**
         * 获取当前时间yy-MM-dd hh:mm:ss 日期的时分秒
         * @returns {string}
         * @memberOf Utils
         */
        getCurrentDate: function () {
            var date = new Date();
            var month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
            var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
            return date.getFullYear() + "-" + month + "-" + day;
        },
        getPastMonthDate: function () {
            var times = (new Date()).getTime() - 30 * 1000 * 3600 * 24;
            var date = new Date(times);
            var month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
            var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
            return date.getFullYear() + "-" + month + "-" + day;
        },
        /**
         * 获取当前时间yy-MM-dd hh:mm:ss 日期的时分秒
         * @returns {string}
         * @memberOf Utils
         */
        getCurrentTime: function () {
            var date = new Date();
            var month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
            var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
            var hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
            var minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
            var second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
            return date.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
        },


        getDaysDiffAbs: function (date1, date2) {
            if (!date1 || !date2) {
                return 0;
            } else {
                return Math.abs((date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000));
            }
        },

        getHoursDiffAbs: function (date1, date2) {
            if (!date1 || !date2) {
                return 0;
            } else {
                return Math.abs((date1.getTime() - date2.getTime()) / (60 * 60 * 1000));
            }
        },

        /*获取光标位置*/
        getCursorPos: function(obj)
        {
            var CaretPos = 0;
            // IE Support 
            if (document.selection) {
                obj.focus(); //获取光标位置函数 
                var Sel = document.selection.createRange();
                Sel.moveStart('character', -obj.value.length);
                CaretPos = Sel.text.length;
            }
            // Firefox/Safari/Chrome/Opera support 
            else if (obj.selectionStart || obj.selectionStart == '0') {
                CaretPos = obj.selectionEnd;
            }
            return (CaretPos);
        },
        /* 
         定位光标 
         */
        setCursorPos:function(obj, pos)
        {
            if (obj.setSelectionRange) { //Firefox/Safari/Chrome/Opera
                obj.focus(); //
                obj.setSelectionRange(pos, pos);
            } else if (obj.createTextRange) { // IE
                var range = obj.createTextRange();
                range.collapse(true);
                range.moveEnd('character', pos);
                range.moveStart('character', pos);
                range.select();
            }
        },
        /* 
         替换后定位光标在原处,可以这样调用onkeyup=replaceAndSetPos(this,/[^/d]/g,''); 
         */
        replaceAndSetPos:function(obj){
            var pos = this.getCursorPos(obj);//保存原始光标位置 
            var temp = obj.value; //保存原始值 
            //obj.value=temp.replace(pattern,text);//替换掉非法值 
            obj.value = this.getVinCodeCheckedValue(obj);//替换掉非法值 

            //截掉超过长度限制的字串（此方法要求已设定元素的maxlength属性值）
            var max_length = obj.getAttribute ? parseInt(obj.getAttribute("maxlength")) : "";
            if (obj.value.length > max_length) {
                var str1 = obj.value.substring(0, pos - 1);
                var str2 = obj.value.substring(pos, max_length + 1);
                obj.value = str1 + str2;
            }

            pos = pos - (temp.length - obj.value.length);//当前光标位置 
            this.setCursorPos(obj, pos);//设置光标 

            return obj.value;
        },

        /**
         * VIN码按键处理
         * @param {jQuery} $vinInputField
         */
        pressValidKeyAsVin: function ($vinInputField) {
            var key;
            if (document.all) {
                key = window.event.keyCode;
            } else {
                key = window.event.which;
            }
            if (!(key && (isNumberKeyCode(key) || isEnglishLetter(key) || isOtherAllowKey(key)))) {
                window.event.returnValue = false;
                // 如果是中文输入法状态
                if (key === 229) {
                    $vinInputField.val(this.replaceAndSetPos($vinInputField));
                }
            }
        },
        /**
         * 模仿出2列的表格使内容垂直居中,并且每列都拥有同样的高度
         * @param {Array} elements
         * @param {Number} columns
         */
        simulateTable: function (elements, columns) {
            var $elements = elements;
            var temp = [];
            //构造出[[{},{}],[{},{}]] 的二维数组
            for (var x = 0; x < $elements.length; x++) {
                var childArray = [];
                for (var y = 0; y < columns; y++) {
                    if (!$elements[x + x + y]) {
                        continue;
                    }
                    childArray.push([$elements[x + x + y]]);
                }
                temp.push(childArray);
            }

            //循环数组取到最大高度并赋值
            $.each(temp, function (n, data) {
                var tempCopy = [];
                for (var y = 0; y < columns; y++) {
                    var dataH = data[y] ? $(data[y]).height() : 0;
                    tempCopy.push(dataH);
                }
                for (var y = 0; y < columns; y++) {
                    $(data[y]).height(tempCopy.sort()[columns - 1]);
                }
            });
        },

        /**
         * 是否值Deferred对象
         * @param {jQuery.Deferred} obj
         */
        isDeferred: function (obj) {
            return obj && obj.promise && typeof obj.promise == "function";
        },

        /**
         * 处理键盘事件 禁止后退键（Backspace）密码或单行、多行文本框除外
         * @param {Event} e
         * @returns {boolean}
         */
        forbidBackSpace: function (e) {
            var ev = e || window.event; //获取event对象   
            var obj = ev.target || ev.srcElement; //获取事件源   
            var t = obj.type || obj.getAttribute('type'); //获取事件源类型   
            //获取作为判断条件的事件类型   
            var vReadOnly = obj.readOnly;
            var vDisabled = obj.disabled;
            //处理undefined值情况   
            vReadOnly = (vReadOnly == undefined) ? false : vReadOnly;
            vDisabled = (vDisabled == undefined) ? true : vDisabled;
            //当敲Backspace键时，事件源类型为密码或单行、多行文本的，   
            //并且readOnly属性为true或disabled属性为true的，则退格键失效   
            var flag1 = ev.keyCode == 8 && (t == "password" || t == "text" || t == "textarea") && (vReadOnly == true || vDisabled == true);
            //当敲Backspace键时，事件源类型非密码或单行、多行文本的，则退格键失效   
            var flag2 = ev.keyCode == 8 && t != "password" && t != "text" && t != "textarea";
            //判断   
            if (flag2 || flag1) return false;
        },


        /**
         * 解决乘法浮点数精度问题，例如：0.285*100，0.275*100
         * @param {number} num 数值
         * @param {number} multiplier 乘数
         * @returns {number} 结果
         */
        multiplyInt: function (num, multiplier) {
            return new Decimal(num).times(multiplier).toNumber();
        },


        /**
         * Number的toFixed方法有bug, 3.445 -> 3.45
         * @param {Number} number
         * @param {Number} precision
         * @returns {number}
         */
        toFixed: function (number, precision) {
            //var multiplier = Math.pow(10, precision),
            //    wholeNumber = Math.round(this.multiplyInt(number, multiplier));
            //return wholeNumber / multiplier;
            return new Decimal(number).toFixed(precision);
        },

        /**
         * 设置选择框的值(CheckBox，radio)
         * @param name
         * @returns {string}
         */
        getCheckBoxRadioValue: function (name, defaultValue) {
            var checkboxValue = [];
            $("input[name='" + name + "']:checked").each(function () {
                checkboxValue.push($(this).val());
            });
            return checkboxValue.toString() || defaultValue || "";
        },

        /**
         * 设置选择框的值(CheckBox，radio)
         * @param name {String}
         * @param values {String}
         * @param defaultValue {String+}
         */
        setCheckBoxRadioValue: function (name, values, defaultValue) {
            if (values) {
                $(values.split(",")).each(function () {
                    $("input[name='" + name + "'][value='" + String(this) + "']").prop("checked", true);
                });
            } else if (defaultValue) {
                $(defaultValue.split(",")).each(function () {
                    $("input[name='" + name + "'][value='" + String(this) + "']").prop("checked", true);
                });
            }
        },
        compare: function (data1, data2, isString) {
            if (data1 && data1.getTime && data2 && data2.getTime) {
                data1 = data1.getTime();
                data2 = data2.getTime();
            }

            if ((data1 === null || data1 === "" || data1 === undefined) && (data2 === null || data2 === "" || data2 === undefined)) {
                return 0;
            }

            if (data1 === 0 && data2 === 0) {
                return 0;
            }

            if (data1 === null || data1 === "" || data1 === undefined) {
                return -1;
            }
            if (data2 === null || data2 === "" || data2 === undefined) {
                return 1;
            }
            if (isString) {
                return data1.localeCompare(data2);
            }
            return Number(data1) > Number(data2) ? 1 : -1;
        },

        /**
         * 整除两个数值
         * @param exp1 被除数
         * @param exp2 除数
         * @returns {number}
         */
        divide: function (exp1, exp2) {
            var n1 = Math.round(exp1); //四舍五入
            var n2 = Math.round(exp2); //四舍五入
            var rslt = n1 / n2; //除
            if (rslt >= 0) {
                rslt = Math.floor(rslt); //返回值为小于等于其数值参数的最大整数值。
            }
            else {
                rslt = Math.ceil(rslt); //返回值为大于等于其数字参数的最小整数。
            }
            return rslt;
        },

        /**
         * sorting arrays on multiple keys.
         * Please refer to https://github.com/Teun/thenBy.js
         */
        firstCondition: (function () {
            function e(f) {
                f.thenCondition = t;
                return f;
            }

            function t(y, x) {
                x = this;
                return e(function (a, b) {
                    return x(a, b) || y(a, b);
                });
            }

            return e;
        })(),

        /**
         * 缩放图片使其居中
         * @param imgElement 图片元素
         * @param imgWrap 放置图片的窗口
         */
        centerImgInBox: function (imgElement, imgWrap) {
            var w = imgElement.width();
            var h = imgElement.height();
            var boxW = imgWrap.width();
            var boxH = imgWrap.height();
            var ratio = w / h;
            var top;
            if (w < boxW && h < boxH) {
                top = (boxH - h) / 2;
                imgElement.css({"margin-top": top});
            } else {
                if (ratio > boxW / boxH) {
                    h = boxW / ratio;
                    top = (boxH - h) / 2;
                    imgElement.css({
                        "width": boxW,
                        "height": boxW / ratio,
                        "margin-top": top
                    });
                } else {
                    w = boxH * ratio;
                    imgElement.css({
                        "width": w,
                        "height": boxH
                    });
                }
            }
        },

        //除法
        //解决小数点精度丢失问题
        accDiv : function (arg1, arg2) {
            var t1 = 0, t2 = 0, r1, r2;
            try {
                t1 = arg1.toString().split(".")[1].length;
            } catch (e) {
            }
            try {
                t2 = arg2.toString().split(".")[1].length;
            } catch (e) {
            }
            with (Math) {
                r1 = Number(arg1.toString().replace(".", ""));
                r2 = Number(arg2.toString().replace(".", ""));
                return Utils.accMul((r1 / r2), pow(10, t2 - t1));
            }
        },

        //乘法
        //说明：javascript的乘法结果会有误差，在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
        accMul : function (arg1, arg2) {
            var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
            try {
                m += s1.split(".")[1].length;
            } catch (e) {
            }
            try {
                m += s2.split(".")[1].length;
            } catch (e) {
            }
            return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
        },

        //加法
        //解决小数点精度丢失问题
        accAdd : function (arg1, arg2) {
            var r1, r2, m;
            try {
                r1 = arg1.toString().split(".")[1].length;
            } catch (e) {
                r1 = 0;
            }
            try {
                r2 = arg2.toString().split(".")[1].length;
            } catch (e) {
                r2 = 0;
            }
            m = Math.pow(10, Math.max(r1, r2));
            return (arg1 * m + arg2 * m) / m;
        },

        //减法
        //解决小数点精度丢失问题
        subtr : function (arg1, arg2) {
            var r1, r2, m, n;
            try {
                r1 = arg1.toString().split(".")[1].length;
            } catch (e) {
                r1 = 0;
            }
            try {
                r2 = arg2.toString().split(".")[1].length;
            } catch (e) {
                r2 = 0;
            }
            m = Math.pow(10, Math.max(r1, r2));
            n = (r1 >= r2) ? r1 : r2;
            return ((arg1 * m - arg2 * m) / m).toFixed(n);
        },

        /**
         * 获取 项目路径
         */
        getContextPath: function () {
            return CONTEXT_PATH;
        },

        /**
         * 获取 是否登录成功
         */
        success: function (request) {
            var success = true;
            $.ajax({
                url: CONTEXT_PATH + request,
                type: "GET",
                async: false,
                contentType: "application/json;charset=UTF-8",
                dataType: "json",
                success: function(data) {
                    // if (data.user_name == null) {
                    if (data.user_name === '' || data.user_name.trim().length === 0) {
                        success = false;
                    }
                }
            });
            return success;
        },

        /**
         * 获取 初始化的一些参数
         */
        getInitConstant: function () {
            return INIT_CONSTANT;
        },
        
        /**
         * 获取 全部产品类型
         */
        getAllShopProductType: function () {
            return ALL_SHOP_PRODUCT_TYPE;
        },

        /**
         * 获取 店铺状态
         */
        getAllShopStatus: function () {
            return ALL_SHOP_STATUS;
        },
        /**
         * 获取 店铺状态
         */
        getAllShopStatus: function () {
            return ALL_SHOP_STATUS;
        },

        /**
         * 获取 api 代码
         */
        getAllApiCode: function () {
            return ALL_API_CODE;
        },
        
        /**
         * 获取 api 类型
         */
        getAllApiType: function () {
            return ALL_API_TYPE;
        },

        /**
         * 获取 热门城市
         */
        getAllHotCity: function () {
            return ALL_HOT_CITY;
        },

        /**
         * 获取 公司类型
         */
        getAllCompanyType: function () {
            return ALL_COMPANY_TYPE;
        },

        /**
         * 获取 公司类型
         */
        getCompanyType: function (data) {
            var companyTypeCode = data.field.search_companyType;
            var companyType = '';
            for (var i = 0; i < ALL_COMPANY_TYPE.length; i++) {
                if (companyTypeCode == ALL_COMPANY_TYPE[i].key) {
                    companyType = ALL_COMPANY_TYPE[i].value;
                    break;
                }
            }
            return companyType;
        },

        /**
         * 变更表格选中状态
         */
        checkStatus: function(obj) {
            //判断是否被选中
            if (obj.tr.find('.layui-form-checkbox').hasClass('layui-form-checked')) {
                //设置为未选中的样式
                obj.tr.find('.layui-form-checkbox').removeClass('layui-form-checked');
            } else {
                //设置为选中的样式
                obj.tr.find('.layui-form-checkbox').addClass('layui-form-checked');
            }

        }


    };
})(jQuery);


